#ifndef BASE_AUTODETECTPROXY_H_
#define BASE_AUTODETECTPROXY_H_

#include "signalthread.h"
#include "proxyinfo.h"
#include "constructormagic.h"
#include "proxydetect.h"

namespace base
{
	///////////////////////////////////////////////////////////////////////////////
	// AutoDetectProxy
	///////////////////////////////////////////////////////////////////////////////

	class AsyncResolver;
	class AsyncSocket;

	class AutoDetectProxy : public SignalThread
	{
	public:
		explicit AutoDetectProxy(const std::string& user_agent);

		const ProxyInfo& proxy() const { return proxy_; }

		void set_server_url(const std::string& url)
		{
			server_url_ = url;
		}
		void set_proxy(const SocketAddress& proxy)
		{
			proxy_.type = PROXY_UNKNOWN;
			proxy_.address = proxy;
		}
		void set_auth_info(bool use_auth, const std::string& username,
			const CryptString& password)
		{
			if (use_auth)
			{
				proxy_.username = username;
				proxy_.password = password;
			}
		}

		// Default implementation of GetProxySettingsForUrl. Override for sepcial
		// implementation.
		virtual bool GetProxyForUrl(const char* agent, const char* url, ProxyInfo* proxy)
		{
			return GetProxySettingsForUrl(agent, url, proxy, true);
		}

		enum 
		{ 
			MSG_TIMEOUT = SignalThread::ST_MSG_FIRST_AVAILABLE,
			ADP_MSG_FIRST_AVAILABLE
		};

	protected:
		virtual ~AutoDetectProxy();

		// SignalThread Interface
		virtual void DoWork();
		virtual void OnMessage(Message *msg);

		void Next();
		void Complete(ProxyType type);

		void OnConnectEvent(AsyncSocket* socket);
		void OnReadEvent(AsyncSocket* socket);
		void OnCloseEvent(AsyncSocket* socket, int error);
		void OnResolveResult(SignalThread* thread);
		void DoConnect();

	private:
		std::string agent_;
		std::string server_url_;
		ProxyInfo proxy_;
		AsyncResolver* resolver_;
		AsyncSocket* socket_;
		int next_;

		DISALLOW_IMPLICIT_CONSTRUCTORS(AutoDetectProxy);
	};
}

#endif	// BASE_AUTODETECTPROXY_H_